home *** CD-ROM | disk | FTP | other *** search
/ Aminet 5 / Aminet 5 - March 1995.iso / Aminet / dev / misc / LEDA_gene.lha / LEDA-3.1c-generic / prog / plane / seg_int_rat.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-05  |  13.8 KB  |  616 lines

  1. #include <LEDA/sweep_segments.h>
  2. #include <LEDA/sortseq.h>
  3. #include <LEDA/prio.h>
  4. #include <math.h>
  5. #include <LEDA/rational.h>
  6.  
  7.  
  8. /*
  9. #define EPS  0.00001
  10. #define EPS2 0.0000000001
  11. */
  12.  
  13. #define double rational
  14.  
  15. const double EPS  = 0;
  16. const double EPS2 = 0;
  17.  
  18. class SW_POINT;
  19. class SW_SEGMENT;
  20. typedef SW_POINT* SW_point;
  21. typedef SW_SEGMENT* SW_segment;
  22.  
  23. enum SW_point_type {Cross=0,Rightend=1,Leftend=2}; 
  24.  
  25. class SW_POINT
  26. {
  27.   friend class SW_SEGMENT;
  28.  
  29.   SW_segment seg;
  30.   int     kind;
  31.   double  x;
  32.   double  y;
  33.  
  34.   public:
  35.  
  36.   SW_POINT(double a,double b)  
  37.   { 
  38.     x=a; y=b; seg=0; kind=Cross;
  39.    }
  40.  
  41.  
  42.  
  43.   SW_POINT(point p)         
  44.   { 
  45.     x=p.xcoord();y=p.ycoord();seg=0;kind=Cross;
  46.    }
  47.  
  48.  
  49.   LEDA_MEMORY(SW_POINT);
  50.  
  51.   friend double    get_x(SW_point);
  52.   friend double    get_y(SW_point);
  53.   friend int       get_kind(SW_point);
  54.   friend SW_segment get_seg(SW_point);
  55.  
  56.   friend bool intersection(SW_segment, SW_segment, SW_point&);
  57. };
  58.  
  59. inline double    get_x(SW_point p)    { return p->x; }
  60. inline double    get_y(SW_point p)    { return p->y; }
  61. inline int       get_kind(SW_point p) { return p->kind; }
  62. inline SW_segment get_seg(SW_point p)  { return p->seg; }   
  63.  
  64. static int compare(SW_point& p1,SW_point& p2)
  65. { if (p1==p2) return 0;
  66.  
  67.   int c = compare(get_x(p1), get_x(p2));
  68.  
  69.   if (c) return c;
  70.  
  71.   int diffk = get_kind(p1)-get_kind(p2);
  72.  
  73.   if (diffk != 0) return diffk;
  74.  
  75.   return compare(get_y(p1), get_y(p2));
  76.  
  77. }
  78.  
  79.  
  80.  
  81. /*
  82.  
  83. static int compare(SW_point& p1,SW_point& p2)
  84. { if (p1==p2) return 0;
  85.  
  86.   double diffx = get_x(p1) - get_x(p2);
  87.   if (diffx >  EPS2) return  1;
  88.   if (diffx < -EPS2) return -1;
  89.  
  90.   int    diffk = get_kind(p1)-get_kind(p2);
  91.   if (diffk != 0) return diffk;
  92.  
  93.   double diffy = get_y(p1) - get_y(p2);
  94.   if (diffy >  EPS2) return  1;
  95.   if (diffy < -EPS2) return -1;
  96.  
  97.   return 0;
  98.  
  99. }
  100. */
  101.  
  102.  
  103. class SW_SEGMENT
  104. {
  105.   SW_point startpoint;
  106.   SW_point endpoint;
  107.   double  slope;
  108.   double  yshift;
  109.   node  left_node;
  110.   int   orient;
  111.   int   color;
  112.   int   name;
  113.  
  114.  
  115.   public:
  116.  
  117.   SW_SEGMENT(SW_point, SW_point,int,int);     
  118.  
  119.  ~SW_SEGMENT() { delete startpoint; delete endpoint; }     
  120.  
  121.   LEDA_MEMORY(SW_SEGMENT);
  122.  
  123.   friend SW_point get_startpoint(SW_segment);
  124.   friend SW_point get_endpoint(SW_segment);
  125.   friend double get_slope(SW_segment);
  126.   friend double get_yshift(SW_segment);
  127.   friend int  get_orient(SW_segment);
  128.   friend int  get_color(SW_segment);
  129.   friend int  get_name(SW_segment);
  130.   friend node get_left_node(SW_segment);
  131.   friend void set_left_node(SW_segment, node);
  132.  
  133.   friend bool intersection(SW_segment, SW_segment, SW_point&);
  134. };
  135.  
  136.  
  137. inline SW_point get_startpoint(SW_segment seg)     { return seg->startpoint; }
  138. inline SW_point get_endpoint(SW_segment seg)       { return seg->endpoint; }
  139. inline double get_slope(SW_segment seg)           { return seg->slope; }
  140. inline double get_yshift(SW_segment seg)          { return seg->yshift; }
  141. inline int  get_orient(SW_segment seg)            { return seg->orient; }
  142. inline int  get_color(SW_segment seg)             { return seg->color; }
  143. inline int  get_name(SW_segment seg)              { return seg->name; }
  144. inline node get_left_node(SW_segment seg)         { return seg->left_node; }
  145. inline void set_left_node(SW_segment seg, node v) { seg->left_node = v; }
  146.  
  147.  
  148.  
  149. SW_SEGMENT::SW_SEGMENT(SW_point p1,SW_point p2,int c, int n)    
  150.   {
  151.     left_node  = nil;
  152.     color      = c;
  153.     name       = n;
  154.  
  155.     if (compare(p1,p2) < 0)
  156.      { startpoint = p1; 
  157.        endpoint = p2; 
  158.        orient = 0;
  159.       }
  160.     else
  161.      { startpoint = p2; 
  162.        endpoint = p1; 
  163.        orient = 1;
  164.       }
  165.  
  166.     startpoint->kind = Leftend; 
  167.     endpoint->kind = Rightend; 
  168.     startpoint->seg = this; 
  169.     endpoint->seg = this;
  170.  
  171.     if (endpoint->x != startpoint->x)
  172.     {
  173.       slope = (endpoint->y - startpoint->y)/(endpoint->x - startpoint->x);
  174.       yshift = startpoint->y - slope * startpoint->x;
  175.  
  176.       startpoint->x -= EPS;
  177.       startpoint->y -= EPS * slope;
  178.       endpoint->x += EPS;
  179.       endpoint->y += EPS * slope;
  180.     }
  181.     else //vertical segment
  182.     { startpoint->y -= EPS;
  183.       endpoint->y   += EPS;
  184.      }
  185.   }
  186.  
  187.  
  188. static double x_sweep;
  189. static double y_sweep;
  190.  
  191.  
  192. static int compare(SW_segment& s1,SW_segment& s2)
  193. {
  194.   double y1 = get_slope(s1)*x_sweep+get_yshift(s1);
  195.   double y2 = get_slope(s2)*x_sweep+get_yshift(s2);
  196.  
  197.   double diff = y1-y2;
  198.  
  199.   if (diff >  EPS2) return  1;
  200.   if (diff < -EPS2) return -1;
  201.  
  202.   if (get_slope(s1) == get_slope(s2)) 
  203.         return compare(get_x(get_startpoint(s1)), get_x(get_startpoint(s2)));
  204.  
  205.   if (y1 <= y_sweep+EPS2)
  206.         return compare(get_slope(s1),get_slope(s2));
  207.   else
  208.         return compare(get_slope(s2),get_slope(s1));
  209.  
  210. }
  211.  
  212.  
  213. void Print(SW_segment& x) 
  214. { SW_point s = get_startpoint(x);
  215.   SW_point e = get_endpoint(x);
  216.   cout << 
  217.     string("[(%f,%f)----(%f,%f)]",float(get_x(s)),float(get_y(s)),
  218.                                   float(get_x(e)),float(get_y(e)));
  219. }
  220.  
  221.  
  222. static priority_queue<seq_item,SW_point> X_structure;
  223.  
  224. static sortseq<SW_segment,pq_item> Y_structure;
  225.  
  226.  
  227. bool intersection(SW_segment seg1,SW_segment seg2, SW_point& inter)
  228. {
  229.   if (seg1->slope == seg2->slope)
  230.     return false;
  231.   else
  232.   {
  233.     //x-coordinate  of the intersection
  234.     double Cross_x = (seg2->yshift - seg1->yshift) / (seg1->slope - seg2->slope);
  235.  
  236.     if (Cross_x <= x_sweep) return false;
  237.  
  238.     double s1 = seg1->startpoint->x;
  239.     double s2 = seg2->startpoint->x;
  240.     double e1 = seg1->endpoint->x;
  241.     double e2 = seg2->endpoint->x;
  242.  
  243.     if (s2>Cross_x || s1>Cross_x || Cross_x>e1 || Cross_x>e2) return false;
  244.  
  245.     //y-coordinate of the intersection
  246.     double Cross_y = (seg1->slope * Cross_x + seg1->yshift);
  247.     inter =  new SW_POINT(Cross_x,Cross_y);
  248.  
  249.     return true;
  250.   }
  251. }
  252.  
  253.  
  254. static pq_item Xinsert(seq_item i, SW_point p) 
  255.   return X_structure.insert(i,p);
  256. }
  257.  
  258. static SW_point Xdelete(pq_item i) 
  259. {
  260.   SW_point p = X_structure.inf(i);
  261.   X_structure.del_item(i);
  262.   return p;
  263. }
  264.  
  265.  
  266. static node New_Node(GRAPH<point,int>& G,double x, double y )
  267. { return G.new_node(point(x,y)); }
  268.  
  269. static void New_Edge(GRAPH<point,int>& G,node v, node w, SW_segment l )
  270. { if (get_orient(l)==0)
  271.        G.new_edge(v,w,get_color(l));
  272.   else G.new_edge(w,v,get_color(l));
  273. }
  274.  
  275.  
  276. void handle_vertical_segment(GRAPH<point,int>& SUB, SW_segment l)
  277.   SW_point p = new SW_POINT(get_x(get_startpoint(l)),get_y(get_startpoint(l)));
  278.   SW_point q = new SW_POINT(get_x(get_endpoint(l)),get_y(get_endpoint(l)));
  279.  
  280.   SW_point r = new SW_POINT(get_x(p)+double(1),get_y(p));
  281.   SW_point s = new SW_POINT(get_x(q)+double(1),get_y(q));
  282.  
  283.   SW_segment bot = new SW_SEGMENT(p,r,0,0);
  284.   SW_segment top = new SW_SEGMENT(q,s,0,0);
  285.  
  286.   seq_item bot_it = Y_structure.insert(bot,nil);
  287.   seq_item top_it = Y_structure.insert(top,nil);
  288.   seq_item sit;
  289.  
  290.   node u,v,w;
  291.   SW_segment seg;
  292.   
  293.  
  294.   for(sit=Y_structure.succ(bot_it); sit != top_it; sit=Y_structure.succ(sit))
  295.   { seg = Y_structure.key(sit);
  296.  
  297.     double cross_y = (get_slope(seg) * get_x(p) + get_yshift(seg));
  298.  
  299.     v = get_left_node(seg);
  300.     if (v==nil)
  301.     { w = New_Node(SUB,get_x(p),cross_y);
  302.       set_left_node(seg,w);
  303.      }
  304.     else
  305.     { double vx = SUB[v].xcoord();
  306.       if ( vx < get_x(p)-EPS2) 
  307.       { w = New_Node(SUB,get_x(p),cross_y);
  308.         New_Edge(SUB,v,w,seg);
  309.         set_left_node(seg,w);
  310.        }
  311.       else w = v;
  312.      }
  313.  
  314.     u = get_left_node(l);
  315.     if (u!=nil && u!=w) New_Edge(SUB,u,w,l);
  316.     set_left_node(l,w);
  317.  
  318.    }
  319.   
  320.   delete l;
  321.   delete top;
  322.   delete bot;
  323.     
  324.   Y_structure.del_item(bot_it);
  325.   Y_structure.del_item(top_it);
  326.  
  327.  }
  328.  
  329.  
  330. void Sweep_Segments(const list<segment>& L1, 
  331.                     const list<segment>& L2, GRAPH<point,int>& SUB)
  332. {
  333.   SW_point    p,inter;
  334.   SW_segment  seg, l,lsit,lpred,lsucc,lpredpred;
  335.   pq_item  pqit,pxmin;
  336.   seq_item sitmin,sit,sitpred,sitsucc,sitpredpred;
  337.  
  338.  
  339.   int count=1;
  340.  
  341.   //initialization of the X-structure
  342.  
  343.   segment s;
  344.  
  345.   forall(s,L1) 
  346.    { SW_point p = new SW_POINT(s.start());
  347.      SW_point q = new SW_POINT(s.end());
  348.      seg = new SW_SEGMENT(p,q,0,count++);
  349.      Xinsert(nil,get_startpoint(seg));
  350.    }
  351.  
  352.   count = -1;
  353.  
  354.   forall(s,L2) 
  355.    { SW_point p = new SW_POINT(s.start());
  356.      SW_point q = new SW_POINT(s.end());
  357.      seg = new SW_SEGMENT(p,q,1,count--);
  358.      Xinsert(nil,get_startpoint(seg));
  359.    }
  360.  
  361.  
  362.   count = 0;
  363.  
  364.   x_sweep = -MAXINT;
  365.   y_sweep = -MAXINT;
  366.  
  367.  
  368.   while(!X_structure.empty())
  369.   {
  370.     pxmin = X_structure.find_min();
  371.     p = X_structure.inf(pxmin);
  372.  
  373.     sitmin = X_structure.key(pxmin);
  374.  
  375.     Xdelete(pxmin);
  376.  
  377.  
  378.  
  379.     if (get_kind(p) == Leftend)
  380.  
  381.     //left endpoint
  382.     { 
  383.  
  384.       l = get_seg(p); 
  385.  
  386.       x_sweep = get_x(p);
  387.       y_sweep = get_y(p);
  388.  
  389.  
  390.       if (get_x(p) == get_x(get_endpoint(l)))
  391.         handle_vertical_segment(SUB,l);
  392.       else
  393.       {
  394.  
  395. /*
  396.       sit = Y_structure.lookup(l);
  397.       if (sit!=nil)  
  398.            error_handler(1,"plane sweep: sorry, overlapping segments");
  399. */
  400.  
  401.  
  402.       sit = Y_structure.insert(l,nil);
  403.  
  404.       Xinsert(sit,get_endpoint(l));
  405.  
  406.       sitpred = Y_structure.pred(sit);
  407.       sitsucc = Y_structure.succ(sit);
  408.  
  409.       if (sitpred != nil) 
  410.       { if ((pqit = Y_structure.inf(sitpred)) != nil)
  411.           delete Xdelete(pqit);
  412.  
  413.         lpred = Y_structure.key(sitpred);
  414.  
  415.         Y_structure.change_inf(sitpred,nil);
  416.  
  417.         if (intersection(lpred,l,inter))
  418.             Y_structure.change_inf(sitpred,Xinsert(sitpred,inter));
  419.       }
  420.  
  421.  
  422.       if (sitsucc != nil)
  423.       { lsucc = Y_structure.key(sitsucc);
  424.         if (intersection(lsucc,l,inter))
  425.            Y_structure.change_inf(sit,Xinsert(sit,inter));
  426.       }
  427.      } /* else if vertical */
  428.  
  429.     }
  430.     else if (get_kind(p) == Rightend)
  431.          //right endpoint
  432.          { 
  433.            x_sweep = get_x(p);
  434.            y_sweep = get_y(p);
  435.  
  436.            sit = sitmin;
  437.  
  438.            sitpred = Y_structure.pred(sit);
  439.            sitsucc = Y_structure.succ(sit);
  440.  
  441.            SW_segment seg = Y_structure.key(sit);
  442.  
  443.            Y_structure.del_item(sit);
  444.  
  445.            delete seg;
  446.  
  447.            if((sitpred != nil)&&(sitsucc != nil))
  448.            {
  449.              lpred = Y_structure.key(sitpred);
  450.              lsucc = Y_structure.key(sitsucc);
  451.              if (intersection(lsucc,lpred,inter))
  452.                 Y_structure.change_inf(sitpred,Xinsert(sitpred,inter));
  453.            }
  454.          }
  455.          else
  456.          /*point of intersection*/
  457.          { 
  458.            node w = New_Node(SUB,get_x(p),get_y(p));
  459.  
  460.            count++;
  461.  
  462.            /* Let L = list of all lines intersecting in p 
  463.  
  464.               we compute sit     = L.head();
  465.               and        sitpred = L.tail();
  466.  
  467.               by scanning the Y_structure in both directions 
  468.               starting at sitmin;
  469.  
  470.            */
  471.  
  472.            /* search for sitpred upwards from sitmin: */
  473.  
  474.            Y_structure.change_inf(sitmin,nil);
  475.  
  476.            sitpred = Y_structure.succ(sitmin);
  477.  
  478.  
  479.            while ((pqit=Y_structure.inf(sitpred)) != nil)
  480.            { SW_point q = X_structure.inf(pqit);
  481.              if (compare(p,q) != 0) break; 
  482.              X_structure.del_item(pqit);
  483.              Y_structure.change_inf(sitpred,nil);
  484.              sitpred = Y_structure.succ(sitpred);
  485.             }
  486.  
  487.  
  488.            /* search for sit downwards from sitmin: */
  489.  
  490.            sit = sitmin;
  491.  
  492.            seq_item sit1;
  493.            
  494.            while ((sit1=Y_structure.pred(sit)) != nil)
  495.            { pqit = Y_structure.inf(sit1);
  496.              if (pqit == nil) break;
  497.              SW_point q = X_structure.inf(pqit);
  498.              if (compare(p,q) != 0) break; 
  499.              X_structure.del_item(pqit);
  500.              Y_structure.change_inf(sit1,nil);
  501.              sit = sit1;
  502.             }
  503.  
  504.  
  505.  
  506.            // insert edges to p for all SW_segments in sit, ..., sitpred into SUB
  507.            // and set left node to w 
  508.  
  509.            lsit = Y_structure.key(sitpred);
  510.  
  511.            node v = get_left_node(lsit);
  512.            if (v!=nil) New_Edge(SUB,v,w,lsit);
  513.            set_left_node(lsit,w);
  514.  
  515.            for(sit1=sit; sit1!=sitpred; sit1 = Y_structure.succ(sit1))
  516.            { lsit = Y_structure.key(sit1);
  517.  
  518.              v = get_left_node(lsit);
  519.              if (v!=nil) New_Edge(SUB,v,w,lsit);
  520.              set_left_node(lsit,w);
  521.             }
  522.  
  523.            lsit = Y_structure.key(sit);
  524.            lpred=Y_structure.key(sitpred);
  525.            sitpredpred = Y_structure.pred(sit);
  526.            sitsucc=Y_structure.succ(sitpred);
  527.  
  528.  
  529.            if (sitpredpred != nil)
  530.             { 
  531.               lpredpred=Y_structure.key(sitpredpred);
  532.  
  533.               if ((pqit = Y_structure.inf(sitpredpred)) != nil)
  534.                 delete Xdelete(pqit);
  535.  
  536.               Y_structure.change_inf(sitpredpred,nil);
  537.  
  538.  
  539.               if (intersection(lpred,lpredpred,inter))
  540.                 Y_structure.change_inf(sitpredpred,
  541.                                        Xinsert(sitpredpred,inter));
  542.              }
  543.  
  544.  
  545.            if (sitsucc != nil)
  546.             {
  547.               lsucc=Y_structure.key(sitsucc);
  548.  
  549.               if ((pqit = Y_structure.inf(sitpred)) != nil)
  550.                 delete Xdelete(pqit);
  551.                  
  552.               Y_structure.change_inf(sitpred,nil);
  553.  
  554.               if (intersection(lsucc,lsit,inter))
  555.                   Y_structure.change_inf(sit,Xinsert(sit,inter));
  556.              }
  557.  
  558.  
  559. // reverse the subsequence sit, ... ,sitpred  in the Y_structure
  560.  
  561.            x_sweep = get_x(p);
  562.            y_sweep = get_y(p);
  563.  
  564.            Y_structure.reverse_items(sit,sitpred);
  565.  
  566.           delete p;
  567.  
  568.          } // intersection
  569.  
  570.   }
  571.  
  572.   X_structure.clear();
  573.  
  574. }
  575.  
  576. main()
  577.   int N = read_int("N = ");
  578.  
  579.   list<segment> seglist1,seglist2;
  580.   
  581.   while (N--) 
  582.   { double x1 = random(-1000,-100);
  583.     double y1 = random(-1000,1000);
  584.     double x2 = random(100,1000);
  585.     double y2 = random(-1000,1000);
  586.     seglist1.append(segment(x1,y1,x2,y2));
  587.    }
  588.  
  589.   GRAPH<point,int> SUB;
  590.  
  591.  
  592.   float T;
  593.  
  594.   T = used_time();
  595.   cout << "SWEEP_SEGMENTS (double)  :         ";
  596.   cout.flush(); 
  597.   SWEEP_SEGMENTS(seglist1,seglist2,SUB);
  598.   cout<< string(" # = %d time = %6.2f sec",SUB.number_of_nodes(), used_time(T));
  599.   newline;
  600.  
  601.   SUB.clear();
  602.  
  603.   T = used_time();
  604.   cout << "Sweep_Segments (leda-rational):    ";
  605.   cout.flush(); 
  606.   Sweep_Segments(seglist1,seglist2,SUB);
  607.   cout<< string(" # = %d time = %6.2f sec",SUB.number_of_nodes(), used_time(T));
  608.   newline;
  609.  
  610. return 0;
  611.  
  612. }
  613.